/*
    This source file is part of GeNa project.
    Copyright © GeNa project 2008
    For the latest info, see http://code.google.com/p/genaproject/ or  http://lumpyproject.forums-rpg.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>. */

#include "view_window.h"
#include "application.h"
#include "map_manager.h"
#include "axis.h"

#include <dae.h>
#include <dom/domCOLLADA.h>

BEGIN_EVENT_TABLE(ViewWindow, GLWindow)
	EVT_MOUSE_EVENTS(ViewWindow::onMouseEvent)
	EVT_KEY_DOWN(ViewWindow::onKeyDown)
END_EVENT_TABLE()

void ViewWindow::init()
{
}

void ViewWindow::update(int interval)
{
    SetCurrent();
    scanKeys();

    if( m_mouseCaptured)
    {
        int f = interval*(forward - backward);
        int r = interval*(right - left);
        int u = interval*(up - down);

        if( f | r | u)
            m_camera.addKeyboardMove(f,r,u);
    }

    float position[] = {0.0, 3.0, 3.0, 0.0};
    float local_view[] = {0.0};
    float ambient[] = {0.1745, 0.01175, 0.01175};
    float diffuse[] = {0.61424, 0.04136, 0.04136};
    float specular[] = {0.727811, 0.626959, 0.626959};

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);

    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

    //glFrontFace(GL_CW);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
    glMaterialf(GL_FRONT, GL_SHININESS, 0.6*128.0);



    glClearColor(0.83, 0.83, 0.83, 1.0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //Camera
	int width;
	int height;
	GetSize(&width, &height);

    glViewport(0,0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(70, width/(float)height, 0.1, 10000);

    m_camera.apply();

    if( wireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    mapManagerInstance.current->draw();
    if( wireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glDisable(GL_LIGHTING);
    m_axis.draw();

    SwapBuffers();
}

void ViewWindow::onMouseEvent(wxMouseEvent &event)
{
    SetFocus();

    if( m_mouseCaptured)
    {
        if( event.MiddleDown())
        {
            SetCursor(*wxSTANDARD_CURSOR);
            m_mouseCaptured = false;
        }
        else if( event.Moving())
            onMouseMove(event);
    }
    else
    {
        if( event.MiddleDown())
        {
            SetCursor(wxCURSOR_BLANK);
            m_mouseCaptured = true;

            int width, height;
            GetSize(&width, &height);
            WarpPointer(width/2, height/2);
        }
    }
}

void ViewWindow::onMouseMove(wxMouseEvent &event)
{
    if( m_mouseCaptured)
    {
        int width, height;
        GetSize(&width, &height);
        WarpPointer(width/2, height/2);

        m_camera.addMouseOrientation(event.GetX() - width/2, event.GetY() - height/2);
    }
}

// FIXME (Égru#1#): Export keys layout to a file instead of using macro definitions
#ifdef BEPO_LAYOUT
#define VW_FORWARD_KEY  (wxKeyCode)(L'é')
#define VW_BACKWARD_KEY (wxKeyCode)('U')
#define VW_LEFT_KEY     (wxKeyCode)(L'A')
#define VW_RIGHT_KEY    (wxKeyCode)('I')
#define VW_DOWN_KEY     (wxKeyCode)('B')
#define VW_UP_KEY       (wxKeyCode)('P')
#define VW_WIREFRAME_KEY (wxKeyCode)('E')

#elif AZERTY_LAYOUT
#define VW_FORWARD_KEY  (wxKeyCode)('Z')
#define VW_BACKWARD_KEY (wxKeyCode)('S')
#define VW_LEFT_KEY     (wxKeyCode)('Q')
#define VW_RIGHT_KEY    (wxKeyCode)('D')
#define VW_DOWN_KEY     (wxKeyCode)('A')
#define VW_UP_KEY       (wxKeyCode)('E')
#define VW_WIREFRAME_KEY (wxKeyCode)('F')

#else //Default case : Qwerty layout
#define VW_FORWARD_KEY  (wxKeyCode)('W')
#define VW_BACKWARD_KEY (wxKeyCode)('S')
#define VW_LEFT_KEY     (wxKeyCode)('A')
#define VW_RIGHT_KEY    (wxKeyCode)('D')
#define VW_DOWN_KEY     (wxKeyCode)('Q')
#define VW_UP_KEY       (wxKeyCode)('E')
#define VW_WIREFRAME_KEY (wxKeyCode)('F')

#endif

void ViewWindow::onKeyDown(wxKeyEvent &event)
{
    if( event.GetKeyCode() == VW_WIREFRAME_KEY)
        wireframe = !wireframe;
    event.Skip();
}

void ViewWindow::scanKeys()
{
    bool normal = !( wxGetKeyState(WXK_CONTROL) | wxGetKeyState(WXK_ALT) | wxGetKeyState( WXK_SHIFT) | wxGetKeyState( WXK_COMMAND));

    forward = (wxGetKeyState( VW_FORWARD_KEY) | wxGetKeyState(WXK_UP)) & normal;
    backward = (wxGetKeyState( VW_BACKWARD_KEY) | wxGetKeyState(WXK_DOWN)) & normal;
    left = (wxGetKeyState( VW_LEFT_KEY) | wxGetKeyState(WXK_LEFT)) & normal;
    right = (wxGetKeyState( VW_RIGHT_KEY) | wxGetKeyState(WXK_RIGHT)) & normal;
    up = (wxGetKeyState( VW_UP_KEY) | wxGetKeyState(WXK_PAGEUP)) & normal;
    down = (wxGetKeyState( VW_DOWN_KEY) | wxGetKeyState(WXK_PAGEDOWN)) & normal;
}


